package com.example.config;

import co.elastic.clients.elasticsearch.ElasticsearchClient;
import co.elastic.clients.json.jackson.JacksonJsonpMapper;
import co.elastic.clients.transport.ElasticsearchTransport;
import co.elastic.clients.transport.rest_client.RestClientTransport;
import org.apache.http.HttpHost;
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.client.CredentialsProvider;
import org.apache.http.impl.client.BasicCredentialsProvider;
import org.apache.http.impl.nio.client.HttpAsyncClientBuilder;
import org.apache.http.ssl.SSLContextBuilder;
import org.apache.http.ssl.SSLContexts;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestClientBuilder;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import java.security.cert.X509Certificate;

/**
 * Elasticsearch配置类
 */
@Configuration
public class ElasticsearchConfig {

    @Value("${elasticsearch.host}")
    private String host;

    @Value("${elasticsearch.port}")
    private int port;

    @Value("${elasticsearch.username}")
    private String username;

    @Value("${elasticsearch.password}")
    private String password;

    @Value("${elasticsearch.protocol:https}")
    private String protocol;

    @Value("${elasticsearch.ca-fingerprint:}")
    private String caFingerprint;

    @Value("${elasticsearch.connection-timeout:10000}")
    private int connectionTimeout;

    @Value("${elasticsearch.socket-timeout:60000}")
    private int socketTimeout;

    @Value("${elasticsearch.retry-timeout:30000}")
    private int retryTimeout;

    /**
     * 配置Elasticsearch客户端
     */
    @Bean
    public ElasticsearchClient elasticsearchClient() {
        final CredentialsProvider credentialsProvider = new BasicCredentialsProvider();
        credentialsProvider.setCredentials(
                AuthScope.ANY,
                new UsernamePasswordCredentials(username, password)
        );

        RestClientBuilder builder = RestClient.builder(
                new HttpHost(host, port, protocol)
        )
        .setHttpClientConfigCallback(httpClientBuilder -> {
            httpClientBuilder.setDefaultCredentialsProvider(credentialsProvider);
            
            // 如果是 HTTPS，配置 SSL 上下文
            if ("https".equalsIgnoreCase(protocol)) {
                try {
                    // 创建信任所有证书的 SSL 上下文（开发环境用）
                    // 生产环境建议使用正确的证书验证
                    SSLContext sslContext = SSLContexts.custom()
                            .loadTrustMaterial(null, (chain, authType) -> true)
                            .build();
                    httpClientBuilder.setSSLContext(sslContext);
                    // 禁用主机名验证（仅开发环境）
                    httpClientBuilder.setSSLHostnameVerifier((hostname, session) -> true);
                } catch (Exception e) {
                    throw new RuntimeException("配置 Elasticsearch SSL 上下文失败", e);
                }
            }
            
            return httpClientBuilder;
        })
        .setRequestConfigCallback(requestConfigBuilder -> {
            requestConfigBuilder.setConnectTimeout(connectionTimeout);
            requestConfigBuilder.setSocketTimeout(socketTimeout);
            requestConfigBuilder.setConnectionRequestTimeout(0);
            return requestConfigBuilder;
        });

        ElasticsearchTransport transport = new RestClientTransport(
                builder.build(), new JacksonJsonpMapper());

        return new ElasticsearchClient(transport);
    }
}